#!/usr/bin/python

import re

def switch_in_file(filename, pattern, replacement):
  f = open(filename, 'r')
  file_text = f.read()
  f.close()
  f = open(filename, 'w')
  f.write(re.sub(pattern, replacement, file_text))
  f.close()

boost_dir = raw_input("\nEnter the path of your boost directory.\n-->  ")
if boost_dir[-1] != "/":
  boost_dir += "/"

have_mkl = ""
while have_mkl != "yes" and have_mkl != "no":
  have_mkl = raw_input("\nWill you be using the Intel MKL library?  Enter yes or no.\n-->  ")

if have_mkl == "yes":
  mkl_dir = raw_input("\nEnter the path of your mkl directory (e.g. /usr/local/opt/intel/mkl/10.2.1.017/)\n-->  ")
  if mkl_dir[-1] != "/":
    mkl_dir += "/"
else:
  blas_lapack_link = raw_input("\nEnter the linking command for your BLAS and LAPACK libraries.\n" + \
                               "(e.g. -L/home/user/blas/ -lblas -L/home/user/lapack/ -llapack)\n-->  ")
  blas_fort_prefix = raw_input("\nEnter the prefix due to name mangling for the blas and lapack libraries.\n" + \
                               "Just press <Enter> if there is no prefix.\n-->  ")
  blas_fort_postfix = raw_input("\nEnter the postfix due to name mangling for the blas and lapack libraries.\n" + \
                                "Just press <Enter> if there is no postfix.\n-->  ")

have_mpi = ""
while have_mpi != "yes" and have_mpi != "no":
  have_mpi = raw_input("\nWill you be using MPI?  Enter yes or no.\n-->  ")

have_psi3 = ""
while have_psi3 != "yes" and have_psi3 != "no":
  have_psi3 = raw_input("\nWill you be using PSI3?  Enter yes or no.\n-->  ")
if have_psi3 == "yes":
  psi3_dir = raw_input("\nEnter the path of your psi3 install directory (e.g. /home/you/psi3/install/)\n-->  ")
  if psi3_dir[-1] != "/":
    psi3_dir += "/"

cc = raw_input("\nEnter the command for your c++ compiler (e.g. g++ or mpic++).\n-->  ")

debug = ""
while debug != "yes" and debug != "no":
  debug = raw_input("\nAre you debugging?  Enter yes or no.\n-->  ")

if debug == "yes":
  cc_flags = "-m64 -O0 -g"
else:
  cc_flags = "-m64 -O2"
if have_mkl == "yes":
  cc_flags += " -DHAVE_MKL -pthread "
  #cc_flags += " -DHAVE_MKL -pthread"
if have_mpi == "yes":
  cc_flags += " -DHAVE_MPI"
if have_psi3 == "yes":
  cc_flags += " -DHAVE_PSI3"

# create the makefile
f = open('makefile', 'w')
f.write("# specify boost header file directory\n")
f.write("BOOST_DIR := %s\n" % boost_dir)
f.write("\n")
f.write("# setup for blas/lapack\n")
if have_mkl == "yes":
  f.write("BLAS_LAPACK_INC := -I%sinclude/\n" % mkl_dir)
  f.write("BLAS_LAPACK_LIB := -L%slib/em64t -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread -lm\n" % mkl_dir)
  #f.write("BLAS_LAPACK_LIB := -L%slib/em64t -lguide -lmkl_core -lmkl_intel_thread -lmkl_intel_lp64\n" % mkl_dir)
else:
  f.write("BLAS_LAPACK_INC :=\n")
  f.write("BLAS_LAPACK_LIB := %s\n" % blas_lapack_link)
f.write("\n")
f.write("# setup for pfaffian library\n")
f.write("PFAFFIAN_INC := -I pfapack/fortran/EXAMPLES/cplusplus/\n")
f.write("PFAFFIAN_LIB := pfapack/fortran/libpfapack.a\n")
f.write("\n")
f.write("# setup for PSI3\n")
if have_psi3 == "yes":
  f.write("PSI3_INC := -I%sinclude/\n" % psi3_dir)
  f.write("PSI3_LIB := -L%slib/ -lPSI_dpd -lPSI_qt -lPSI_chkpt -lPSI_iwl -lPSI_psio -lPSI_ciomr -lPSI_ipv1\n" % psi3_dir)
else:
  f.write("PSI3_INC :=\n")
  f.write("PSI3_LIB :=\n")
f.write("\n")
f.write("# set compiler\n")
f.write("CC = %s\n" % cc)
f.write("\n")
f.write("# set compilation flags\n")
f.write("CC_FLAGS := %s\n" % cc_flags)
f.write("\n")
f.write("# specify include directories\n")
f.write("GLOBAL_INC := -I./ -I$(BOOST_DIR) $(BLAS_LAPACK_INC) $(PSI3_INC) $(PFAFFIAN_INC)\n")
f.write("\n")
f.write("# create list of object files\n")
f.write("objects := $(subst src/,obj/,$(subst .cpp,.o,$(wildcard src/*.cpp)))\n")
f.write("\n")
f.write("# create list of dependency files\n")
f.write("dependencies := $(subst src/,dep/,$(subst .cpp,.d,$(wildcard src/*.cpp)))\n")
f.write("\n")
f.write("# when make is run with no arguments, create the executable\n")
f.write(".PHONY : default\n")
f.write("default : bin/pcps.exe\n")
f.write("\n")
f.write("# rules to create the automatically generated input parsing code\n")
f.write("src/input_auto_gen.h : src/input_auto_gen.py\n")
f.write("\tpython src/input_auto_gen.py\n")
f.write("src/input_auto_gen.cpp : src/input_auto_gen.py\n")
f.write("\tpython src/input_auto_gen.py\n")
f.write("\n")
#f.write("# command to run a set of tests\n")
#f.write(".PHONY : test\n")
#f.write("test : \n")
#f.write("	@cd tests; ./run_tests.sh; cd ../;\n")
#f.write("\n")
f.write("# for each object file foo.o, create a dependency file foo.d in the dep/ directory\n")
f.write("$(dependencies) : dep/%.d : src/%.cpp\n")
f.write("\t@echo \"updating dependencies for $<\";\n")
f.write("\t@$(CC) $(CC_FLAGS) $(GLOBAL_INC) -MM $< | sed -e \"s/$*\\.o/obj\\/$*.o dep\\/$*.d/\" > $@;\n")
f.write("\n")
f.write("# read in the rules that list the dependencies for each object and dependency file\n")
f.write("sinclude $(dependencies)\n")
f.write("\n")
f.write("# compile each object file\n")
f.write("$(objects) : obj/%.o : src/%.cpp\n")
f.write("\t$(CC) $(CC_FLAGS) $(GLOBAL_INC) -c $< -o $@;\n")
f.write("\n")
f.write("# create the executable\n")
f.write("bin/pcps.exe : $(objects) pfapack/fortran/libpfapack.a\n")
f.write("\t$(CC) $(CC_FLAGS) $(objects) $(BLAS_LAPACK_LIB) $(PFAFFIAN_LIB) $(PSI3_LIB) -o $@;\n")
f.write("\n")
f.write("# compile pfaffian library\n")
f.write("pfapack/fortran/libpfapack.a : pfapack/fortran/*.f90 pfapack/fortran/*.f\n")
f.write("\tcd pfapack/fortran/ && $(MAKE);\n")
f.write("\n")
f.write("# rule to clean up object and dependency files\n")
f.write(".PHONY : clean\n")
f.write("clean : \n")
f.write("\trm -f obj/*.o;\n")
f.write("\trm -f dep/*.d;\n")
f.write("\trm -f pfapack/fortran/*.o;\n")
#f.write("\trm -f tests/test_1_output.txt;\n")
#f.write("\trm -f tests/test_2_output.txt;\n")
#f.write("\trm -f tests/test_3_output.txt;\n")
#f.write("\trm -f tests/test_4_output.txt;\n")
#f.write("\trm -f tests/pcps_wfn.bin;\n")
f.write("\n")
f.close()

# set the name mangling of blas and lapack fortran functions
if have_mkl == "no":
  replacement_str = "#define FFUNC(a)"
  if len(blas_fort_prefix) > 0:
    replacement_str += (" %s ##" % blas_fort_prefix)
  replacement_str += " a"
  if len(blas_fort_postfix) > 0:
    replacement_str += (" ## %s" % blas_fort_postfix)
  switch_in_file("src/blas_lapack.h", "\#define FFUNC\(a\).*", replacement_str)

# Turn assertions on or off
if debug == "yes":
  switch_in_file("src/pcps.h", ".*\#define NDEBUG.*", "//#define NDEBUG")
else:
  switch_in_file("src/pcps.h", ".*\#define NDEBUG.*", "#define NDEBUG")
